<?php

/*
 * connect to the database
 */
require "./includes/db_connection.php";

/*
 * SQL prepared queries
 */
$sql_unitid = "SELECT greenhouseid FROM greenhouse WHERE token=?";

$sql_checkid = "SELECT b.username
				FROM greenhouse as a, user as b 
				WHERE b.username=?
				AND a.greenhouseid=?
				AND a.user_id=b.userid";

$sql_addrec = "INSERT INTO record (greenhouse_id, dt, type, v1, v2, v3) VALUES (?,?,?,?,?,?)";
$sql_addcnf = "INSERT INTO config (greenhouse_id, type, number, v1, v2) VALUES (?,?,?,?,?)";
$sql_getcnf = "SELECT * FROM config WHERE greenhouse_id=?";
$sql_clearcnf = "DELETE FROM config WHERE greenhouse_id=?";
$sql_checkreqcnf = "SELECT request_cnf FROM greenhouse WHERE greenhouseid=?";
$sql_checkupdatecnf = "SELECT update_cnf FROM greenhouse WHERE greenhouseid=?";
$sql_received = "UPDATE greenhouse SET update_cnf=FALSE WHERE greenhouseid=?";
$sql_sent = "UPDATE greenhouse SET request_cnf=FALSE WHERE greenhouseid=?";


/**
 * Get unit id from received token
 *
 * @param string $token Unit unique token
 * @return integer Unit ID belonging to token
 */
function get_unitid($token) {
	global $db, $sql_unitid;
	try {
		$ps = $db->prepare($sql_unitid);
		$ps->execute(array($token));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [get unitid]");
	}
	return $row['greenhouseid'];
}

/**
 * Get match between greenhouse unit id and user name
 *
 *
 * @param string $user User name
 * @param int $unitid Greenhouse unit id
 * @return boolean Match result
 */
function checkunit($user, $unitid) {
	global $db, $sql_checkid;

	// check unit id and user name
	try {
		$ps = $db->prepare($sql_checkid);
		$ps->execute(array($user, $unitid));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
	} catch (Exception $e) {
		die("<fail>\nChyba SQL [check unitid]<br>$e");
	}
	// name and unit not match, access denied
	if(empty($row)) {
		return FALSE;
	}
	else {
		return TRUE;
	}

}

/**
 * Check request config flag and send tag to unit
 *
 * @param string $unitid Greenhouse unit id
 */
function checkreqcnf($unitid) {
	global $db, $sql_checkreqcnf;

	try {
		$ps = $db->prepare($sql_checkreqcnf);
		$ps->execute(array($unitid));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
		if($row['request_cnf'] == TRUE) {
			echo("<s>");
		}
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [check request]");
	}
}

/**
 * Check update config flag
 *
 * @param string $unitid Greenhouse unit id
 * @return boolean True, is update flag is up
 */
function isupdatecnf($unitid) {
	global $db, $sql_checkupdatecnf;

	try {
		$ps = $db->prepare($sql_checkupdatecnf);
		$ps->execute(array($unitid));
		$row = $ps->fetch(PDO::FETCH_ASSOC);
		if($row['update_cnf'] == TRUE) {
			return true;
		}
	} catch(Exception $e) {
		return false;
	}
}

/**
 * Send all config data from DB to unit
 *
 * @param string $unitid Greenhouse unit id
 */
function send_cnf($unitid) {
	global $db, $sql_getcnf;

	try {
		$ps = $db->prepare($sql_getcnf);
		$ps->execute(array($unitid));
		foreach ($ps as $row) {
			echo($row['type'] . " " . $row['number'] . " " . $row['v1'] . " " . $row['v2'] . "\n");
		}
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [get config]");
	}
}


/**
 * Add record from greenhouse to db
 *
 * @param string $unitid Greenhouse unit id
 * @param datetime $time Date and Time of record
 * @param char $type Type of record - Environmental or Action
 * @param byte $v1 First value - Temperature or Trigger
 * @param byte $v2 Second value - Humidity or Device
 * @param byte $v3 Third value - Soil Moisture or State of device
 */
function addrecord($unitid, $time, $type, $v1, $v2, $v3) {
	global $db, $sql_addrec;

	try {
		$ps = $db->prepare($sql_addrec);
		$ps->execute(array($unitid, $time, $type, $v1, $v2, $v3));
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [insert record]");
	}
}

/**
 * Config data received, set request config flag to FALSE
 *
 *
 * @param string $unitid Greenhouse unit id
 */
function cnfreceived($unitid) {
	global $db, $sql_sent;

	try {
		$ps = $db->prepare($sql_sent);
		$ps->execute(array($unitid));
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [config received]");
	}
}

/**
 * Add config from greenhouse to db
 *
 * @param string $unitid Greenhouse unit id
 * @param char $type Type of config data
 * @param byte $number Number of config line
 * @param byte $v1 First value - Time, Min value, Delay
 * @param byte $v2 Second value - Delay, Max value
 */
function addconfig($unitid, $type, $number, $v1, $v2) {
	global $db, $sql_addcnf;

	try {
		$ps = $db->prepare($sql_addcnf);
		$ps->execute(array($unitid, $type, $number, $v1, $v2));
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [insert config]");
	}

	cnfreceived($unitid);
}

/**
 * Clear config and prepare for incomming data
 * 
 * 
 * @param string $unitid Greenhouse unit id
 */
function clearcnf($unitid) {
	global $db, $sql_clearcnf;
	
	try {
		$ps = $db->prepare($sql_clearcnf);
		$ps->execute(array($unitid));
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [clear config]");
	}
}

/**
 * Check unit and send data
 *
 *
 * @param string $user User name
 * @param string $token Greenhouse key
 */
function check($user, $token) {
	global $db;

	// extract unit id from token
	$unitid = get_unitid($token);
	// unit id not fount, access denied
	if(empty($unitid)) {
		die("<a>0");
	}
	// check match user with unitid
	if(checkunit($user, $unitid)) {
		echo("<a>1");
	}
	else {
		die("<a>0");
	}

	// check request flag
	checkreqcnf($unitid);
	// check update flag

	if(isupdatecnf($unitid)) {
		echo("<r>\n");
		send_cnf($unitid);
	}
	// send terminate tag
	echo("<//>");
}

/**
 *
 *
 * @param string $user User name
 * @param string $token Greenhouse communication key
 * @param string $data Data from greenhouse
 */
function send($user, $token, $data) {

	// extract unit id from token
	$unitid = get_unitid($token);
	// unit id not found, access denied
	if(empty($unitid)) {
		die("bad token: $token</>");
	}

	// check match user with unitid
	if(!checkunit($user, $unitid)) {
		die("user not match: $user </>");
	}

	// parse data
	$type = substr($data, 0, 1);
	switch ($type) {
		// clear config data in db
		case 'C' :
			clearcnf($unitid);
			break;
		// environmental record
		case 'E' :
			$time = strtotime(substr($data, 1, 6).' '.substr($data, 7, 8));
			$temp = substr($data, 15, 2);
			$hum = substr($data, 17, 3);
			$soil = substr($data, 20, 3);

			// add record to db
			addrecord($unitid, date('Y-m-d H:i:s', $time), $type, $temp, $hum, $soil);
			break;
			// action record
		case 'A' :
			$time = strtotime(substr($data, 1, 6).' '.substr($data, 7, 8));
			$trigg = substr($data, 15, 1);
			$act = substr($data, 16, 1);
			$state = substr($data, 17, 1);
			// add record to db
			addrecord($unitid, date('Y-m-d H:i:s', $time), $type, $trigg, $act, $state);
			break;

		case 'V' :
		case 'W' :
		case 'D' :
			/* parse config string */
			$splited = explode("_", $data);
			if(count($splited) > 2) {
				$type = $splited[0];
				$num = $splited[1];
				$val1 = $splited[2];

				if(count($splited) > 3) {
					$val2 = $splited[3];
				}
				else {
					$val2 = "0";
				}
				// add config to db
				addconfig($unitid, $type, $num, $val1, $val2);
			}
			break;
	}
	// send successfull terminated
	echo("<o>");

}
/**
 * Greenhouse unit get all data, set update config flag to FALSE
 *
 *
 * @param string $unitid Greenhouse unit id
 */
function received($user, $token) {

	global $db, $sql_received;

	// extract unit id from token
	$unitid = get_unitid($token);
	// unit id not fount, access denied
	if(empty($unitid)) {
		die("</>");
	}

	// get match user with unitid
	if(!checkunit($user, $unitid)) {
		die("</>");
	}

	// update update config flag
	try {
		$ps = $db->prepare($sql_received);
		$ps->execute(array($unitid));
	} catch(Exception $e) {
		die("<fail>\nChyba SQL [received]");
	}

	echo("<o>");
}

/**
 *
 *   BODY
 *
 */

/*
 * Get input data from client
 */
$action = $_GET['action'];
$data = $_GET['da'];
$name = $_GET['name'];
$key = $_GET['key'];

/*
 * Select action
 */

switch($action) {
	case 'check' :
		// return time always
		date_default_timezone_set('Europe/Prague');
		$dt = date_create_from_format('U', time());
		date_timezone_set($dt, new DateTimeZone('Europe/Prague'));
		echo("<t>");
		echo(date_format($dt, 'U') + date_offset_get($dt));
		// check data and send info to unit
		check($name, $key);
		break;

	case 'send' :
		// get data from unit
		send($name, $key, $data);
		break;

	case 'received' :
		// unit received data, reset update flag
		received($name, $key);
		break;
}

exit();
?>